﻿using DependencyAnalysis;
using DependencyAnalysis.DataModel;
using NUnit.Framework;

namespace NUnitExample
{
    [TestFixture]
    public class TypeQualityTest : DependencyTest
    {
        private static void VerifyCoherantTypes(ModuleDescriptor module)
        {
            Setup.Verifier.VerifyThat<TypeDescriptor>((x, state) =>
            {
                var c = Setup.Metrics.LackOfCohesion(x);
                var fields = Setup.Metrics.NumberOfFields(x);
                var methods = Setup.Metrics.NumberOfMethods(x);
                if (c > 1.0 && fields > 10 && methods > 10)
                {
                    state.Message = string.Format(
                        "cohesion={0} fields={1} methods={2}",
                        string.Format("{0:0.00}", c), fields, methods);
                    return false;
                }
                return true;
            },
            x => !(x.IsGenerated || !x.Submodule.Module.IsPartOfProject
                || !x.Submodule.Module.Equals(module))
            );
        }

        [Test]
        public void TypesInDependencyAnalysisAreCoherant()
        {
            var module = DescriptorBuilder.BuildModuleDescriptor(typeof(DependencyAnalysis.Properties.IAssemblyIdentifier).Assembly);
            VerifyCoherantTypes(module);
        }

        [Test]
        public void CyclomaticComplexityIsAtmost200()
        {
            Verifier.VerifyThat((x, state) =>
            {
                var c = Setup.Metrics.CyclomaticComplexity(x);
                if (c > 200)
                {
                    state.Message = string.Format("'cyclomatic complexity={0} > 200'", c);
                    return false;
                }
                return true;
            }, Filters.MyTypes);
        }

        [Test]
        public void NumberOfInstructionsIsAtMost2000()
        {
            Verifier.VerifyThat((x, state) =>
            {
                var c = Setup.Metrics.NumberOfInstructions(x);
                if (c > 2000)
                {
                    state.Message = string.Format("'instructions={0} > 2000'", c);
                    return false;
                }
                return true;
            }, Filters.MyTypes);
        }

        [Test]
        public void NumberOfMethodsIsAtMost30()
        {
            Verifier.VerifyThat((x, state) =>
            {
                var c = Setup.Metrics.NumberOfMethods(x);
                if (c > 30)
                {
                    state.Message = string.Format("'methods={0} > 30'", c);
                    return false;
                }
                return true;
            }, Filters.MyTypes);
        }

        [Test]
        public void NumberOfFieldsIsAtMost30()
        {
            Verifier.VerifyThat((x, state) =>
            {
                var c = Setup.Metrics.NumberOfFields(x);
                if (c > 30)
                {
                    state.Message = string.Format("'fields={0} > 30'", c);
                    return false;
                }
                return true;
            }, Filters.MyTypes);
        }
    }
}
